#include <iostream>

#include <QJsonDocument>
#include <QProcess>
#include <QTcpSocket>
#include <QJsonArray>
#include <QFile>
#include <QMutexLocker>

#include "AnThread.h"


//#define EMIT_ERROR emit response(QJsonDocument.fromJson(QString(AN_ERROR_RESPONSE).toUtf8()).object());



/**
 * @brief AnThread::_adb_check 检查adb是否存在
 */
void AnThread::_adb_check()
{
	QProcess adb_process;
	QString cmd = adb_path;
    cmd += QString(" version");
	adb_process.start(cmd);
	adb_process.waitForFinished();

	QString output = QString(adb_process.readAllStandardOutput());

	std::cout << "L: " << output.toUtf8().data() << std::endl;
	std::cout << cmd.toUtf8().data() << std::endl;

	QJsonObject json_data;

	if (output.contains(QString("Android"))) {
        json_data.insert(QString(RESULT), QJsonValue(YES));
	} else {
        json_data.insert(QString(RESULT), QJsonValue(NO));
	}

	QJsonObject json_response = _request;
	json_response.insert(QString(STATUS), QJsonValue(QString(RESPONSE)));
	json_response.insert(QString(DATA), QJsonValue(json_data));

	emit response(json_response);
	emit threadFinished(this);

    std::cout << "debug" << std::endl;

}

/**
 * @brief AnThread::_devices_check 获取当前连接的设备列表
 */
void AnThread::_devices_check()
{

    int is_locked_here = 0;
    if (lock_devices_check.tryLock()) {
        is_locked_here = 1;
    }


	QProcess adb_process;
	QString cmd = adb_path;
	cmd += " devices -l";
	adb_process.start(cmd);
	adb_process.waitForFinished();

	//QString output = QString(adb_process.readAllStandardOutput());
	char buf[1024];
	QString tmp_line;
	int flag = 0;

	QJsonObject resp = _request;

	resp.insert(STATUS, QJsonValue(RESPONSE));

	QJsonArray data_devices;
	QJsonObject * data_devices_each = NULL;

	while (adb_process.readLine(buf, 1023) != -1) {
		tmp_line = buf;
		tmp_line.remove(QChar('\n'));

		if (flag == 0 && tmp_line.contains("List of devices attached")) {
			flag = 1;
			continue;
		}

		if (flag == 1 && tmp_line.contains("device ")) {
			data_devices_each = new QJsonObject();
			QStringList split = tmp_line.split(" ", QString::SkipEmptyParts);
			data_devices_each->insert("id", QJsonValue(split[0]));
			for (int t = 0; t < split.size(); t ++) {
				if (((QString) split[t]).contains("product:")) {
					data_devices_each->insert("product", QJsonValue(((QString) split[t]).mid(8)));
				} else if (((QString) split[t]).contains("model:")) {
					data_devices_each->insert("model", QJsonValue(((QString) split[t]).mid(6)));
				} else if (((QString) split[t]).contains("device:")) {
					data_devices_each->insert("device", QJsonValue(((QString) split[t]).mid(7)));
				}
			}

			data_devices.append(QJsonValue(*data_devices_each));
			delete data_devices_each;
			data_devices_each = NULL;
		}
	}

	QJsonObject data;
	data.insert("devices", QJsonValue(data_devices));
    data.insert(RESULT, QJsonValue(YES));
	resp.insert(DATA, QJsonValue(data));

	emit response(resp);

    if (is_locked_here) {
        lock_devices_check.unlock();
    }

	emit threadFinished(this);

}

/**
 * @brief AnThread::_devices_info 获取设备的具体信息
 */
void AnThread::_devices_info()
{

    int is_locked_here = 0;
    if (lock_devices_info.tryLock()) {
        is_locked_here = 1;
    }

	QTcpSocket * socket = new QTcpSocket();
	socket->connectToHost(hostname, port);
	QJsonObject resp = _request;
	QJsonObject data;

	if (!socket->waitForConnected()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);

        if (is_locked_here) {
            lock_devices_info.unlock();
        }

		emit threadFinished(this);
		return;
	}



	socket->write(QJsonDocument(_request).toJson());
	socket->waitForBytesWritten();
	socket->waitForReadyRead();

	QString read_data = "";
	QByteArray tmp_data = "";

	//QJsonObject response_data = _request;

	tmp_data = socket->read(4096);

	if (tmp_data.size() ==  0) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);

        if (is_locked_here) {
            lock_devices_info.unlock();
        }

		emit threadFinished(this);
		return;
	}

	read_data += tmp_data;

	while (tmp_data.size() == 4096) {
		tmp_data = socket->read(4096);
		read_data += tmp_data;
	}

	QJsonDocument resp_doc = QJsonDocument::fromJson(read_data.toUtf8());

	if (resp_doc.isEmpty()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp_doc.object());

        if (is_locked_here) {
            lock_devices_info.unlock();
        }

		emit threadFinished(this);
		return;
	}

	emit response(resp_doc.object());

    if (is_locked_here) {
        lock_devices_info.unlock();
    }

	emit threadFinished(this);
}

//useless
void AnThread::_devices_disconnect() {
    QJsonObject resp = _request;
    resp.insert(STATUS, QJsonValue(RESPONSE));
    QJsonObject data;
    data.insert(RESULT, QJsonValue(SUCCEED));
    resp.insert(DATA, QJsonValue(data));

    if (device_connect_lock.tryLock()) {
        device_connect_lock.unlock();
        emit response(resp);
        emit threadFinished(this);
        return;
    }

    device_close_lock.lock();
    device_connect_lock.lock();
    device_close_lock.unlock();
    device_connect_lock.unlock();

    emit response(resp);
    emit threadFinished(this);
    return;
}

//useless
/**
 * @brief AnThread::_connect_check 检查指定设备是否在连接
 */
void AnThread::_connect_check()
{
	QTcpSocket * socket = new QTcpSocket();
	socket->connectToHost(hostname, port);
	QJsonObject resp = _request;
	QJsonObject data;

	if (!socket->waitForConnected()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
		data.insert(RESULT, QJsonValue(FAILD));
		data.insert(DESC, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);
		emit threadFinished(this);
		return;
	}



	socket->write(QJsonDocument(_request).toJson());
	socket->waitForBytesWritten();
	socket->waitForReadyRead();

	QString read_data = "";
	QByteArray tmp_data = "";

	//QJsonObject response_data = _request;

	tmp_data = socket->read(4096);

	if (tmp_data.size() ==  0) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
		data.insert(RESULT, QJsonValue(FAILD));
		data.insert(DESC, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);
		emit threadFinished(this);
		return;
	}

	read_data += tmp_data;

	while (tmp_data.size() == 4096) {
		tmp_data = socket->read(4096);
		read_data += tmp_data;
	}

	QJsonDocument resp_doc = QJsonDocument::fromJson(read_data.toUtf8());

	if (resp_doc.isEmpty()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
		data.insert(RESULT, QJsonValue(FAILD));
		data.insert(DESC, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);
		emit threadFinished(this);
		return;
	}


	resp.insert(STATUS, QJsonValue(RESPONSE));
	data.insert(RESULT, QJsonValue(SUCCEED));
	resp.insert(DATA, resp);

	emit response(resp);
	emit threadFinished(this);
}


/**
 * @brief AnThread::_connect_build 与指定设备建立连接,成功后在后台检查连接状态
 */
void AnThread::_connect_build()
{

    int is_locked_here = 0;
    if (lock_connect_build.tryLock()) {
        is_locked_here = 1;
    }

	QString device_id = _request.value("data").toObject().value("id").toString();
	QString cmd = adb_path;
	cmd += " -s ";
	cmd += device_id;
	cmd += " forward tcp:";
	cmd += QString::number(port);
	cmd += " tcp:";
	cmd += QString::number(port);

	std::cout << cmd.toUtf8().data() << std::endl;

	QProcess adb_process;
	adb_process.setProcessChannelMode(QProcess::MergedChannels);
	adb_process.start(cmd);
	adb_process.waitForFinished();

	QJsonObject resp = _request;
	resp.insert(STATUS, QJsonValue(RESPONSE));
	QJsonObject data;
	//data.insert(RESULT, QJsonValue())

	QString output = QString(adb_process.readAllStandardOutput());
	std::cout << output.toUtf8().data() << std::endl;
	if (output.contains("error")) {
        data.insert(RESULT, QJsonValue(NO));
		resp.insert(DATA, QJsonValue(data));
		emit response(resp);

        if (is_locked_here) {
            lock_connect_build.unlock();
        }

		emit threadFinished(this);
		return;
	}

	//resp.insert(DATA, QJsonValue(data));

	QString cmd_start_activity = adb_path;
	cmd_start_activity += " -s ";
	cmd_start_activity += device_id;
	cmd_start_activity += " shell am start com.wsgalaxy.anmanager/com.wsgalaxy.anmanager.MainActivity";

	QProcess process_start_activity;
	process_start_activity.setProcessChannelMode(QProcess::MergedChannels);
	process_start_activity.start(cmd_start_activity);
	process_start_activity.waitForFinished();

	QString output_start_activity = QString(process_start_activity.readAllStandardOutput());

	if (output_start_activity.contains("Error:")) {
        data.insert(RESULT, QJsonValue(NO));
		resp.insert(DATA, QJsonValue(data));
		emit response(resp);

        if (is_locked_here) {
            lock_connect_build.unlock();
        }

		emit threadFinished(this);
		return;
	}

    data.insert(RESULT, QJsonValue(YES));

    if (is_locked_here) {
        lock_connect_build.unlock();
    }

    resp.insert(DATA, QJsonValue(data));
    emit response(resp);

    //连接维持
    QObject::connect(this, SIGNAL(sys_response(QJsonObject)),
                     sys_callback, SLOT(response_slot(QJsonObject)));

    emit sys_response(resp);


    device_connect_lock.lock();
    current_devices_id = device_id;

    QJsonObject check_connect_resq;
    check_connect_resq.insert(NAME, QJsonValue("check_connect"));
    check_connect_resq.insert(STATUS, QJsonValue(REQUEST));

    int device_disconnect  = 0;
    QByteArray socket_read_data;

    //int i;

    //QTcpSocket * check_socket = NULL;
    QTcpSocket * check_socket = new QTcpSocket();
    check_socket->connectToHost(hostname, port);
    if (!check_socket->waitForConnected()) {
        device_disconnect = 1;
        check_socket->close();
        delete check_socket;
    }


    while (!device_disconnect && device_close_lock.tryLock()) {
        device_close_lock.unlock();

        //std::cout << i << std::endl;
/*
        check_socket = new QTcpSocket();
        check_socket->connectToHost(hostname, port);

        if (!check_socket->waitForConnected()) {
            device_disconnect = 1;
            check_socket->close();
            delete check_socket;
            break;
        }
*/
        check_socket->write(QJsonDocument(check_connect_resq).toJson());
        //check_socket->waitForBytesWritten();
        check_socket->waitForReadyRead();

        socket_read_data = check_socket->read(4096);

        if (socket_read_data.size() == 0) {
            device_disconnect = 1;
            check_socket->close();
            delete check_socket;
            break;
        }

        QThread::sleep(1);
    }

    if (device_disconnect == 1) {
        QJsonObject resp;
        resp.insert(NAME, QJsonValue("connect_accident"));
        resp.insert(STATUS, QJsonValue(RESPONSE));
        emit sys_response(resp);
    } else {
        QJsonObject resp;
        resp.insert(NAME, QJsonValue("connect_close"));
        resp.insert(STATUS, QJsonValue(RESPONSE));
        emit sys_response(resp);
    }

    device_connect_lock.unlock();
	emit threadFinished(this);
}


void AnThread::_connect_close() {

    int is_locked_here = 0;
    if (lock_connect_close.tryLock()) {
        is_locked_here = 1;
    }

    QObject::connect(this, SIGNAL(sys_response(QJsonObject)),
                     sys_callback, SLOT(response_slot(QJsonObject)));
    device_close_lock.lock();
    device_connect_lock.lock();
    device_connect_lock.unlock();
    device_close_lock.unlock();

    QJsonObject resp;
    QJsonObject resp_data;
    resp_data.insert(RESULT, QJsonValue(YES));

    resp = _request;
    resp.insert(STATUS, RESPONSE);
    resp.insert(DATA, resp_data);
    emit response(resp);
    //emit sys_response(resp);

    if (is_locked_here) {
        lock_connect_close.unlock();
    }

    emit threadFinished(this);
}

//useless
void AnThread::_connect_accident() {

}


/**
 * @brief AnThread::_app_list 获取应用列表
 */
void AnThread::_app_list()
{

    int is_locked_here = 0;
    if (lock_app_list.tryLock()) {
        is_locked_here = 1;
    }

	QTcpSocket * socket = new QTcpSocket();
	socket->connectToHost(hostname, port);
	QJsonObject resp = _request;
	QJsonObject data;

	if (!socket->waitForConnected()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);

        if (is_locked_here) {
            lock_app_list.unlock();
        }

		emit threadFinished(this);
		return;
	}



	socket->write(QJsonDocument(_request).toJson());
	socket->waitForBytesWritten();
	socket->waitForReadyRead();

	QString read_data = "";
	QByteArray tmp_data = "";

	//QJsonObject response_data = _request;

	tmp_data = socket->read(4096);

	if (tmp_data.size() ==  0) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp);

        if (is_locked_here) {
            lock_app_list.unlock();
        }

		emit threadFinished(this);
		return;
	}

	read_data += tmp_data;

	while (tmp_data.size() == 4096) {
		tmp_data = socket->read(4096);
		read_data += tmp_data;
	}

	QJsonDocument resp_doc = QJsonDocument::fromJson(read_data.toUtf8());

	if (resp_doc.isEmpty()) {
		resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
		resp.insert(DATA, QJsonValue(data));

		emit response(resp_doc.object());

        if (is_locked_here) {
            lock_app_list.unlock();
        }

		emit threadFinished(this);
		return;
	}

	emit response(resp_doc.object());

    if (is_locked_here) {
        lock_app_list.unlock();
    }

	emit threadFinished(this);
}

/**
 * @brief AnThread::_app_install 安装应用程序
 */
void AnThread::_app_install()
{

    int is_locked_here = 0;
    if (lock_app_install.tryLock()) {
        is_locked_here = 1;
    }

    QString device_id = current_devices_id;
	QString apk_path = _request.value(DATA).toObject().value("path").toString();
	QString cmd = adb_path;
	cmd += " -s ";
	cmd += device_id;
	cmd += " install ";
	cmd += apk_path;

	QProcess adb_process;
	adb_process.setProcessChannelMode(QProcess::MergedChannels);
	adb_process.start(cmd);
	adb_process.waitForFinished();

	QString output_process = QString(adb_process.readAllStandardOutput());

	QJsonObject resp = _request;
	resp.insert(STATUS, RESPONSE);

	QJsonObject data;

	if (output_process.contains("Success")) {
        data.insert(RESULT, QJsonValue(YES));
	} else {
        data.insert(RESULT, QJsonValue(NO));
	}

	resp.insert(DATA, data);

	emit response(resp);

    if (is_locked_here) {
        lock_app_install.unlock();
    }

	emit threadFinished(this);
}

/**
 * @brief AnThread::_app_uninstall 卸载应用程序
 */
void AnThread::_app_uninstall()
{

    int is_locked_here = 0;
    if (lock_app_uninstall.tryLock()) {
        is_locked_here = 1;
    }

    QString device_id = current_devices_id;
	QString package_name = _request.value(DATA).toObject().value("package_name").toString();

	QString cmd = adb_path;
	cmd += " -s ";
	cmd += device_id;
	cmd += " uninstall ";
	cmd += package_name;

	QProcess adb_process;
	adb_process.setProcessChannelMode(QProcess::MergedChannels);
	adb_process.start(cmd);
	adb_process.waitForFinished();

    QString output_process = QString(adb_process.readAllStandardOutput());

	QJsonObject resp = _request;
	resp.insert(STATUS, RESPONSE);
	QJsonObject data;

	if (output_process.contains("Success") && !output_process.contains("Exception")) {
        data.insert(RESULT, QJsonValue(YES));
	} else {
        data.insert(RESULT, QJsonValue(NO));
	}

	resp.insert(DATA, data);

	emit response(resp);

    if (is_locked_here) {
        lock_app_uninstall.unlock();
    }

	emit threadFinished(this);
}


//useless
void AnThread::_app_backup()
{}

void AnThread::_file_list()
{

    int is_locked_here = 0;
    if (lock_file_list.tryLock()) {
        is_locked_here = 1;
    }

    QTcpSocket * socket = new QTcpSocket();
    socket->connectToHost(hostname, port);
    QJsonObject resp = _request;
    QJsonObject data;

    if (!socket->waitForConnected()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_file_list.unlock();
        }

        emit threadFinished(this);
        return;
    }



    socket->write(QJsonDocument(_request).toJson());
    socket->waitForBytesWritten();
    socket->waitForReadyRead();

    QString read_data = "";
    QByteArray tmp_data = "";

    //QJsonObject response_data = _request;

    tmp_data = socket->read(4096);

    if (tmp_data.size() ==  0) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_file_list.unlock();
        }

        emit threadFinished(this);
        return;
    }

    read_data += tmp_data;

    while (tmp_data.size() == 4096) {
        tmp_data = socket->read(4096);
        read_data += tmp_data;
    }

    QJsonDocument resp_doc = QJsonDocument::fromJson(read_data.toUtf8());

    if (resp_doc.isEmpty()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp_doc.object());

        if (is_locked_here) {
            lock_file_list.unlock();
        }

        emit threadFinished(this);
        return;
    }

    emit response(resp_doc.object());

    if (is_locked_here) {
        lock_file_list.unlock();
    }

    emit threadFinished(this);
}


//uesless
void AnThread::_file_delete()
{}

void AnThread::_file_import()
{

    int is_locked_here = 0;
    if (lock_file_import.tryLock()) {
        is_locked_here = 1;
    }

    QString local_path = _request.value(DATA).toObject().value("local_path").toString();
    QString remote_path = _request.value(DATA).toObject().value("remote_path").toString();

    QString cmd = adb_path;
    cmd += " -s ";
    cmd += current_devices_id;
    cmd += " push \"";

    //cmd += "\"";
    cmd += local_path;
    cmd += "\" \"";
    cmd += remote_path;
    cmd += "\"";

    QProcess adb_process;
    adb_process.setProcessChannelMode(QProcess::MergedChannels);
    adb_process.start(cmd);
    adb_process.waitForFinished(-1);

    QString process_output = QString(adb_process.readAllStandardOutput());


    QJsonObject resp = _request;
    resp.insert(STATUS, RESPONSE);

    QJsonObject data;
    if (process_output.contains("files pushed.") || process_output.contains("file pushed.")) {
        data.insert(RESULT, YES);
    } else {
        data.insert(RESULT, NO);
    }

    resp.insert(DATA, data);

    emit response(resp);

    if (is_locked_here) {
        lock_file_import.unlock();
    }

    emit threadFinished(this);

}

void AnThread::_file_export()
{

    int is_locked_here = 0;
    if (lock_file_export.tryLock()) {
        is_locked_here = 1;
    }

    QString local_path = _request.value(DATA).toObject().value("local_path").toString();
    QString remote_path = _request.value(DATA).toObject().value("remote_path").toString();

    QString cmd = adb_path;
    cmd += " -s ";
    cmd += current_devices_id;
    cmd += " pull \"";

    cmd += remote_path;
    cmd += "\" \"";
    cmd += local_path;
    cmd += "\"";

    QProcess adb_process;
    adb_process.setProcessChannelMode(QProcess::MergedChannels);
    adb_process.start(cmd);
    adb_process.waitForFinished(-1);

    QString process_output = QString(adb_process.readAllStandardOutput());


    QJsonObject resp = _request;
    resp.insert(STATUS, RESPONSE);

    QJsonObject data;
    if (process_output.contains("files pulled.") || process_output.contains("file pulled.")) {
        data.insert(RESULT, YES);
    } else {
        data.insert(RESULT, NO);
    }

    resp.insert(DATA, data);

    emit response(resp);

    if (is_locked_here) {
        lock_file_export.unlock();
    }

    emit threadFinished(this);
}

void AnThread::_contacts_backup()
{
    int is_locked_here = 0;
    if (lock_contacts_backup.tryLock()) {
        is_locked_here = 1;
    }

    QTcpSocket * socket = new QTcpSocket();
    socket->connectToHost(hostname, port);
    QJsonObject resp = _request;
    QJsonObject data;

    if (!socket->waitForConnected()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_contacts_backup.unlock();
        }

        emit threadFinished(this);
        return;
    }



    socket->write(QJsonDocument(_request).toJson());
    socket->waitForBytesWritten();
    socket->waitForReadyRead();

    QString read_data = "";
    QByteArray tmp_data = "";

    //QJsonObject response_data = _request;

    tmp_data = socket->read(4096);

    if (tmp_data.size() ==  0) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_contacts_backup.unlock();
        }

        emit threadFinished(this);
        return;
    }

    read_data += tmp_data;

    while (tmp_data.size() == 4096) {
        tmp_data = socket->read(4096);
        read_data += tmp_data;
    }

    QJsonDocument resp_doc = QJsonDocument::fromJson(read_data.toUtf8());

    if (resp_doc.isEmpty()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp_doc.object());

        if (is_locked_here) {
            lock_contacts_backup.unlock();
        }

        emit threadFinished(this);
        return;
    }


    QJsonArray contacts_list = resp_doc.object()
            .value(DATA).toObject()
            .value("contacts").toArray();


    QFile store_file(_request.value(DATA).toObject()
            .value("path").toString());
    if(!store_file.open(QIODevice::WriteOnly)) {
        QJsonObject error_resp;
        error_resp.insert(NAME, _request.value(NAME).toString());
        error_resp.insert(STATUS, QJsonValue(RESPONSE));
        QJsonObject error_data;
        error_data.insert(RESULT, QJsonValue(NO));
        error_resp.insert(DATA, error_data);
        emit response(error_resp);

        if (is_locked_here) {
            lock_contacts_backup.unlock();
        }

        emit threadFinished(this);
        return;
    }

    //QString contacts_str = QString(QJsonDocument(contacts_list).toJson());
    store_file.write(QJsonDocument(contacts_list).toJson());
    store_file.close();

    resp.insert(STATUS, QJsonValue(RESPONSE));
    QJsonObject resp_data;
    resp_data.insert(RESULT, QJsonValue(YES));
    resp.insert(DATA, resp_data);

    emit response(resp);

    if (is_locked_here) {
        lock_contacts_backup.unlock();
    }

    emit threadFinished(this);

}

void AnThread::_contacts_recovery()
{

    int is_locked_here = 0;
    if (lock_contacts_recovery.tryLock()) {
        is_locked_here = 1;
    }

    QString store_path = _request.value(DATA).toObject()
            .value("path").toString();

    QFile store_file(store_path);
    QJsonObject resp = _request;
    QJsonObject data;

    if (!store_file.exists() || !store_file.open(QIODevice::ReadOnly)) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("file error"));
        resp.insert(DATA, QJsonValue(data));

        store_file.close();

        emit response(resp);

        if (is_locked_here) {
            lock_contacts_recovery.unlock();
        }

        emit threadFinished(this);
        return;
    }

    //QString tmp1 = QString(store_file.readAll());
    QJsonDocument contacts_doc = QJsonDocument::fromJson(store_file.readAll());
    store_file.close();
    if (contacts_doc.isEmpty()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("file error"));
        resp.insert(DATA, QJsonValue(data));


        emit response(resp);

        if (is_locked_here) {
            lock_contacts_recovery.unlock();
        }

        emit threadFinished(this);
        return;
    }

    QJsonObject an_request;
    an_request.insert(NAME, QJsonValue(_request.value(NAME).toString()));
    an_request.insert(STATUS, QJsonValue(REQUEST));
    QJsonObject an_data;
    an_data.insert("contacts", QJsonValue(contacts_doc.array()));
    an_request.insert(DATA, an_data);


    QTcpSocket * socket = new QTcpSocket();
    socket->connectToHost(hostname, port);

    if (!socket->waitForConnected()) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_contacts_recovery.unlock();
        }

        emit threadFinished(this);
        return;
    }



    socket->write(QJsonDocument(an_request).toJson());
    socket->waitForBytesWritten();
    socket->waitForReadyRead();

    QByteArray read_data;

    //QJsonObject response_data = _request;

    read_data = socket->read(4096);

    if (read_data.length() == 0) {
        resp.insert(STATUS, QJsonValue(RESPONSE));
        data.insert(RESULT, QJsonValue(NO));
        data.insert(MSG, QJsonValue("connect faild"));
        resp.insert(DATA, QJsonValue(data));

        emit response(resp);

        if (is_locked_here) {
            lock_contacts_recovery.unlock();
        }

        emit threadFinished(this);
        return;
    }

    emit response(QJsonDocument::fromJson(read_data).object());

    if (is_locked_here) {
        lock_contacts_recovery.unlock();
    }

    emit threadFinished(this);

}


void AnThread::_screencap()
{

    int is_locked_here = 0;
    if (lock_screencap.tryLock()) {
        is_locked_here = 1;
    }

    QProcess adb_process;
    QString cmd = adb_path;
    cmd += QString(" -s ");
    cmd += current_devices_id;
    cmd += " shell screencap -p ";
    cmd += SCREENCAP_LOC_AN;
    adb_process.setProcessChannelMode(QProcess::MergedChannels);
    adb_process.start(cmd);
    adb_process.waitForFinished();

    QString output = QString(adb_process.readAllStandardOutput());


    QJsonObject json_data;
    QJsonObject json_response = _request;
    json_response.insert(QString(STATUS), QJsonValue(QString(RESPONSE)));


    if (output.contains(QString("Error"))) {
        json_data.insert(QString(RESULT), QJsonValue(NO));
        json_response.insert(DATA, json_data);

        emit response(json_response);

        if (is_locked_here) {
            lock_screencap.unlock();
        }

        emit threadFinished(this);
        return;
    }

    QProcess pull_process;
    QString pull_cmd = adb_path;
    pull_cmd += " -s ";
    pull_cmd += current_devices_id;
    pull_cmd += " pull ";
    pull_cmd += SCREENCAP_LOC_AN;
    pull_cmd += " ";
    pull_cmd += SCREENCAP_LOC_PC;
    pull_process.setProcessChannelMode(QProcess::MergedChannels);
    pull_process.start(pull_cmd);
    pull_process.waitForFinished();

    QString pull_op = pull_process.readAllStandardOutput();

    std::cout << pull_op.toUtf8().data() << std::endl;

    if (pull_op.contains("files pulled.") || pull_op.contains("file pulled.")) {
        json_data.insert(RESULT, QJsonValue(YES));
    } else {
        json_data.insert(RESULT, QJsonValue(NO));
    }

    json_response.insert(DATA, QJsonValue(json_data));

    emit response(json_response);

    if (is_locked_here) {
        lock_screencap.unlock();
    }

    emit threadFinished(this);
}




//public
AnThread::AnThread(QJsonObject an_request)
{
	_request = an_request;
}

AnThread::AnThread()
{}

void AnThread::run()
{
	QString request_name = _request.value(QString("name")).toString();

	if (request_name == QString("adb_check")) {
		_adb_check();
	} else if (request_name == QString("devices_check")) {
		_devices_check();
	} else if (request_name == QString("devices_info")) {
		_devices_info();
    } else if (request_name == QString("devices_disconnect")) {
        _devices_disconnect();  //useless
    } else if (request_name == QString("connect_check")) {
        _connect_check();       //useless
	} else if (request_name == QString("connect_build")) {
		_connect_build();
    } else if (request_name == QString("connect_close")) {
        _connect_close();
    } else if (request_name == QString("connect_accident")) {
        _connect_accident();    //useless
    } else if (request_name == QString("app_list")) {
		_app_list();
	} else if (request_name == QString("app_install")) {
		_app_install();
	} else if (request_name == QString("app_uninstall")) {
		_app_uninstall();
	} else if (request_name == QString("app_backup")) {
        _app_backup();      //useless
    } else if (request_name == QString("file_list")) {
        _file_list();
	} else if (request_name == QString("file_delete")) {
        _file_delete();     //useless
	} else if (request_name == QString("file_import")) {
		_file_import();
	} else if (request_name == QString("file_export")) {
		_file_export();
    } else if (request_name == QString("contacts_backup")) {
        _contacts_backup();
    } else if (request_name == QString("contacts_recovery")) {
        _contacts_recovery();
    } else if (request_name == QString("screencap")) {
        _screencap();
    } else {
		QJsonDocument tmp_doc;
		QJsonObject error_response = tmp_doc.fromJson(QString(AN_ERROR_RESPONSE).toUtf8()).object();
		emit response(error_response);
		emit threadFinished(this);
		//EMIT_ERROR
	}

}


void AnThread::setRequest(QJsonObject an_request)
{
	_request = an_request;
}
